import { env, baseUrl } from '@/config/config'
import { auth, gotoLogin } from '@/model/authToLogin/auth'
import { apiAuth } from '@/model/apiAuth/apiAuth'
import { navigate } from '@/util/navigate'
import store from '@/store/store'
let presentPath = ''
let timer: NodeJS.Timeout
async function request(config: Request.IConfig) {
  const apiToken = JSON.parse(uni.getStorageSync('apiToken') || '{}')
  const { token, expires_in } = apiToken
  for (let k in config.data) {
    const isNullish = config.data[k] ?? 'nullish'
    if (isNullish === 'nullish') delete config.data[k]
  }
  try {
    const obj = await apiAuth(expires_in)

    const res = await requestApi(config, obj?.token || token)
    if (config.responseType == 'BLOB') {
      return Promise.resolve(res)
    } else return Promise.resolve(res.data)
  } catch (error) {
    return Promise.reject(error)
  }
}
async function requestApi(config: Request.IConfig, apiToken?: string) {
  const { userState } = store
  try {
    const cfg = (await initRequestConfig(config, apiToken)) as Request.IConfig
    // const invite_code = uni.getStorageSync('appInviteCode') || ''
    const token = userState.userToken.token

    if (config.notToken) {
      // 传入notToken=true ，若本地无token则不传，有则仍旧传
      try {
        cfg.data.token = token
      } catch (error) {}
    }
    const userToken_zh_web = uni.getStorageSync('userToken_zh_web')
    if (userToken_zh_web) {
      cfg.header.Authorization = `Bearer ${userToken_zh_web.token}`
      console.log('设置请求头', cfg)
    }

    let res: any
    if (cfg?.dataType === 'BLOB') {
      const { url, name, file, filePath, fileType, timeout, header, data } = cfg
      res = await uni.uploadFile({ url, filePath, name, timeout, header, file, formData: data })
    } else if (cfg?.responseType === 'BLOB') {
      res = await uni.downloadFile(cfg)
    } else {
      res = await uni.request(cfg)
    }

    if (config.loading !== false) uni.hideLoading()
    if (valueType(res?.data) === 'string') res.data = JSON.parse(res.data)
    if (+res.statusCode === 200 && +res?.data?.code === 200) {
      return Promise.resolve(res)
    } else if (+res.statusCode === 200 && !res?.data?.code) {
      return Promise.resolve(res)
    } else {
      const errMsg = res?.data?.msg ? `${res?.data?.code}/${res?.data?.msg}` : '1001/网络错误，请稍后重试'
      throw new Error(errMsg)
    }
  } catch (error) {
    if (config.loading !== false) uni.hideLoading()
    return Promise.reject(error)
  }
}
async function initRequestConfig(config: Request.IConfig, apiToken?: string) {
  let userToken = uni.getStorageSync('userToken_zh_web') || {}
  const Authorization = `Bearer ${apiToken || ''}`
  const defaultConfig = {
    timeout: 10000 * 10,
    loading: true,
    loadingText: '加载中',
    data: {},
    header: { 'content-type': 'application/json', Authorization },
  }
  config = { method: 'GET', ...defaultConfig, ...config }
  if (config.loading !== false) uni.showLoading({ title: config.loadingText, mask: true })
  if (!config.url.startsWith('http')) config.url = `${baseUrl}${config.url}`
  let pass = true

  if (config?.data?.token) {
    const token = userToken.token
    switch (config.data.token) {
      case 'maybe': {
        config.data.token = token || ''
        break
      }
      case true: {
        config.data.token = token
        if (!config.data.token) {
          setTimeout(() => {
            auth()
          }, 500)
          /* const objToken = await gotoLogin();
          config.data.token = objToken?.["token"]; */
        }
        /* const fakeToken: string = "11111111111111111111111111111111";
        if (env === "dev") config.data.token ||= fakeToken; */
        if (!config.data.token) pass = false
        break
      }
    }
    config.data.token = token || ''
  }

  if (pass === false) throw new Error('203/请先登录')
  if (config.dataType === 'BLOB' || config.responseType === 'BLOB') config.timeout = 60000
  if (config.method === 'POST') {
    if (config.dataType === 'BLOB') {
      config.header = { Authorization }
    } else if (config.dataType === 'JSON') {
      config.header = { 'content-type': 'application/json', Authorization }
    } else {
      config.header = { 'content-type': 'application/x-www-form-urlencoded', Authorization }
    }
  }
  return config
}

const errorTypes = [
  {
    label: '请求超时',
    value: 'request:fail timeout',
  },
  {
    label: '请求失败',
    value: 'request:fail',
  },
  {
    label: '接口数据异常',
    value: `Unexpected token < in JSON at position 0`,
  },
  {
    label: '接口数据异常',
    value: `Unexpected token '<', "<!DOCTYPE "... is not valid JSON`,
  },
]
async function catchException(error: any) {
  console.log(error)
  const msg: string[] = error?.message?.split('/') || []

  const { userState } = store
  if (msg[1]) {
    switch (msg[0]) {
      case '203': {
        break
      }
      case '204': {
        uni.showToast({ title: msg[1], icon: 'none', duration: 2000 })
        setTimeout(() => navigate({ url: '/pReaderCard/bindCard/index', navMethod: 'redirect' }), 1500)
        break
      }
      case '205': {
        uni.setStorageSync('userToken_zh_web', '{}')
        uni.showToast({ title: '登录已过期，请重新登录', duration: 2000, icon: 'none' })
        setTimeout(() => {
          navigate({ url: '/pages/login/index' })
        }, 2000)
        // gotoLogin()

        break
      }
      case '206': {
        uni.setStorageSync('userToken_zh_web', '{}')
        gotoLogin()
        break
      }
      case '301': {
        uni.showModal({
          title: '温馨提示',
          showCancel: false,
          cancelText: '取消',
          confirmText: '确定',
          content: msg[1],
          success: (res) => {
            // #ifdef H5
            document.addEventListener('WeixinJSBridgeReady', () => WeixinJSBridge.call('closeWindow'), false)
            WeixinJSBridge.call('closeWindow')
            // #endif
            // #ifdef MP-WEIXIN
            wx.exitMiniProgram()
            // #endif
          },
        })
        break
      }
      case '302': {
        uni.navigateTo({ url: '/pages/invite/index' })
        const appInviteCode = uni.getStorageSync('appInviteCode')
        if (appInviteCode) {
          uni.showToast({ title: msg[1], icon: 'none', duration: 2000 })
        }
        break
      }
      default: {
        if (msg[1] !== 'none') {
          uni.showToast({ title: msg[1], icon: 'none', duration: 2000 })
        }
        break
      }
    }
  } else {
    const knownError = errorTypes.find((item: any) => item.value === (error.errMsg?.trim() || error?.message?.trim()))
    const errorMsg = knownError ? knownError.label : '网络错误'
    if (errorMsg) uni.showToast({ title: errorMsg, icon: 'none', duration: 2000 })
  }
}
function valueType(v: any): string {
  const str = Object.prototype.toString.call(v)
  const typeArr = str.match(/\[object (.*?)\]/) || []
  return typeArr[1].toLowerCase()
}

export { request, requestApi, catchException }
